﻿using MDPM.EntitiyModels;
using MDPM.Foundation.SpecificationsForEntityModel;
using MDPM.ORM;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace MDPM.DataAccess
{
    /// <summary>
    /// 泛型仓储接口 <see cref="IEntityRepository{T}"/> 的具体实现
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class EntityRepository<T> : IEntityRepository<T> where T : class, IEntityBase, new()
    {
        #region 基础属性约束
        private readonly MDPMDbContext _entitiesContext;                //数据映射
        //private readonly UserManager<ApplicationUser> _userManager;   //用户管理，统一在这里注入，方便后续应用中直接处理
        //private readonly RoleManager<ApplicationRole> _roleManager;   //角色管理

        //以下公开的三个只读属性，是为了方便扩展 IEntityRepository<T> 方法时候使用的
        public MDPMDbContext EntitiesContext { get { return _entitiesContext; } }
        //public UserManager<ApplicationUser> ApplicationUserManager { get { return _userManager; } }
        //public RoleManager<ApplicationRole> ApplicationRoleManager { get { return _roleManager; } }
        #endregion

        /// <summary>
        /// 构造函数，负责相关参数的注入和初始化几个基本参数
        /// </summary>
        /// <param name="context"></param>
        /// <param name="userManager"></param>
        /// <param name="roleManager"></param>
        //public EntityRepository (MDPMDbContext context)
        //{
        //    _entitiesContext = context;
        //    //_userManager = userManager;
        //    //_roleManager = roleManager;
        //}
        public EntityRepository (MDPMDbContext context)
        {
            _entitiesContext = context;
        }

        #region 1.获取指定类型实体数据对象数量的方法，2个重载
        /// <summary>
        /// 获取指定类型 T 的集合元素数量
        /// </summary>
        /// <returns></returns>
        public virtual async Task<int> GetBoAmountAsyn() => await _entitiesContext.Set<T>().CountAsync();
        public virtual async Task<int> GetBoamoutAsyn(Expression<Func<T, bool>> predicate) => await _entitiesContext.Set<T>().CountAsync(predicate);
        #endregion
        
        #region 2.常规获取指定类型 T 单个实体对象的方法，5个重载
        /// <summary>
        /// 获取指定类型 T 集合元素的第一个
        /// </summary>
        /// <returns></returns>
        public virtual async Task<T> GetBoAsyn() => await _entitiesContext.Set<T>().FirstOrDefaultAsync();

        /// <summary>
        /// 根据对象 Id 值获取类型 T 的单个业务对象
        /// </summary>
        /// <param name="id">业务对象 Id 的值</param>
        /// <returns></returns>
        public virtual async Task<T> GetBoAsyn(Guid id) => await _entitiesContext.Set<T>().FirstOrDefaultAsync(x => x.Id == id);
      
        public virtual async Task<T> GerBoAsync(Guid id,params Expression<Func<T,object>>[] includeProperties)
        {
            IQueryable<T> dbSet = _entitiesContext.Set<T>();
            if(includeProperties != null)
            {
                foreach(var includeProperty in includeProperties)
                {
                    dbSet = dbSet.Include(includeProperty);
                }
            }
            return await dbSet.FirstOrDefaultAsync(x => x.Id == id);
        }

        public Task<int> GetBoAmountAsyn(Expression<Func<T, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Task<T> GetBoAsyn(Guid id, params Expression<Func<T, object>>[] includePronperties)
        {
            throw new NotImplementedException();
        }

        public Task<T> GetBoAsyn(Expression<Func<T, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Task<T> GetBoAsyn(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties)
        {
            throw new NotImplementedException();
        }
        #endregion
    }

}
